
`include "common_header.verilog"

//  *************************************************************************
//   File : pcs_tx_state_mc.vhd 
//  *************************************************************************
//   This program is controlled by a written license agreement.
//   Unauthorized Reproduction or Use is Expressly Prohibited. 
// 
//  Copyright (c) 2005 Morethanip GmbH
//  info@morethanip.com
//  *************************************************************************
//  Version: $Id: rx_xgxs_sync.v,v 1.4 2006/06/16 15:55:50 mr Exp $ 
//  Author : Muhammad Anisur Rahman
//  *************************************************************************
//  Description:
// 
//   10 Gigabit Ethernet XGXS Receive Synchronization
// 
//  *************************************************************************

module rx_xgxs_sync (

   reset,
   clk,
  `ifdef USE_CLK_ENA
   clk_ena,
  `endif    
   signal_detect,
   kchar,
   data,
   disp_err,
   dec_error,
   enable_cgalign,
   sync_acqurd);
   
input   reset;          //  Active High Reset
input   clk;            //  156.25MHz Recovered Clock
`ifdef USE_CLK_ENA
input   clk_ena;        //  Enable clk
`endif
input   signal_detect;  //  Signal Detect from PMA
input   [1:0] kchar;    //  Special Character Indication      
input   [15:0] data;    //  Decoded Data     
input   [1:0] disp_err ;//  flag asserted when the Disparity error detected
input   [1:0] dec_error;//  10b Character Error         
output   enable_cgalign; 
output   sync_acqurd;   //  Synchronization Acquired

reg     enable_cgalign; 
reg     sync_acqurd; 

parameter STATE_TYP_LOSS_SYNC  = 4'd0;
parameter STATE_TYP_COMMA_DET1 = 4'd1;
parameter STATE_TYP_COMMA_DET2 = 4'd2;
parameter STATE_TYP_COMMA_DET3 = 4'd3;
parameter STATE_TYP_SYNC_ACQ1  = 4'd4;
parameter STATE_TYP_SYNC_ACQ2  = 4'd5;
parameter STATE_TYP_SYNC_ACQ2A = 4'd6;
parameter STATE_TYP_SYNC_ACQ3  = 4'd7;
parameter STATE_TYP_SYNC_ACQ3A = 4'd8;
parameter STATE_TYP_SYNC_ACQ4  = 4'd9;
parameter STATE_TYP_SYNC_ACQ4A = 4'd10;

reg     [3:0] next_state; 
reg     [3:0] state; 
wire    [1:0] pudi_comma; 
wire    [1:0] char_err; //  10b Character Error
reg     [1:0] good_cgs; 

//  ----------------------------------------------- //
//  Control signals extracted from the Decoded data //
//  pudi_comma=PUDI[/COMMA/]                        //
//  ----------------------------------------------- //

assign pudi_comma[0] = kchar[0] == 1'b 1 & (data[7:0] == 8'h 3C | 
	data[7:0] == 8'h BC | data[7:0] == 8'h FC) ? 1'b 1 : 1'b 0; 
assign pudi_comma[1] = kchar[1] == 1'b 1 & (data[15:8] == 8'h 3C | 
	data[15:8] == 8'h BC | data[15:8] == 8'h FC) ? 1'b 1 : 1'b 0; 
	
assign char_err[0]=disp_err[0] | dec_error[0];
assign char_err[1]=disp_err[1] | dec_error[1];

//  Generator State Machine
//  ----------------------

always @(posedge reset or posedge clk)
   begin : process_1
   if (reset == 1'b 1)
      begin
      state <= STATE_TYP_LOSS_SYNC;	
      end
   else
      begin
      
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif      
      
                state <= next_state;	
      
         `ifdef USE_CLK_ENA
            end
         `endif      
      
      end
   end

always @(state or signal_detect or char_err or pudi_comma or good_cgs)
   begin : process_2
   case (state)
   STATE_TYP_LOSS_SYNC:
      begin
      if (signal_detect == 1'b 1)
         begin
         if (pudi_comma[0] == 1'b 1)
            begin
            if (char_err[1] == 1'b 1)
               begin
               next_state = STATE_TYP_LOSS_SYNC;	
               end
            else if (pudi_comma[1] == 1'b 1 )
               begin
               next_state = STATE_TYP_COMMA_DET2;	
               end
            else
               begin
               next_state = STATE_TYP_COMMA_DET1;	
               end
            end
         else
            begin
            if (pudi_comma[1] == 1'b 1)
               begin
               next_state = STATE_TYP_COMMA_DET1;	
               end
            else
               begin
               next_state = STATE_TYP_LOSS_SYNC;	
               end
            end
         end
      else
         begin
         next_state = STATE_TYP_LOSS_SYNC;	// stay in the same state
         end
      end
   STATE_TYP_COMMA_DET1:
      begin
      if (signal_detect == 1'b 0)
         begin
         next_state = STATE_TYP_LOSS_SYNC;	
         end
      else if (char_err[0] == 1'b 1 )
         begin
         if (pudi_comma[1] == 1'b 1)
            begin
            next_state = STATE_TYP_COMMA_DET1;	
            end
         else
            begin
            next_state = STATE_TYP_LOSS_SYNC;	
            end
         end
      else if (pudi_comma[0] == 1'b 1 )
         begin
         if (char_err[1] == 1'b 1)
            begin
            next_state = STATE_TYP_LOSS_SYNC;	
            end
         else if (pudi_comma[1] == 1'b 1 )
            begin
            next_state = STATE_TYP_COMMA_DET3;	
            end
         else
            begin
            next_state = STATE_TYP_COMMA_DET2;	
            end
         end
      else if (pudi_comma[0] == 1'b 0 )
         begin
         if (char_err[1] == 1'b 1)
            begin
            next_state = STATE_TYP_LOSS_SYNC;	
            end
         else if (pudi_comma[1] == 1'b 1 )
            begin
            next_state = STATE_TYP_COMMA_DET2;	
            end
         else
            begin
            next_state = STATE_TYP_COMMA_DET1;	
            end
         end
      else
         begin
         next_state = STATE_TYP_COMMA_DET1;	
         end
      end
   STATE_TYP_COMMA_DET2:
      begin
      if (signal_detect == 1'b 0)
         begin
         next_state = STATE_TYP_LOSS_SYNC;	
         end
      else if (char_err[0] == 1'b 1 )
         begin
         if (pudi_comma[1] == 1'b 1)
            begin
            next_state = STATE_TYP_COMMA_DET1;	
            end
         else
            begin
            next_state = STATE_TYP_LOSS_SYNC;	
            end
         end
      else if (pudi_comma[0] == 1'b 1 )
         begin
         if (char_err[1] == 1'b 1)
            begin
            next_state = STATE_TYP_LOSS_SYNC;	
            end
         else if (pudi_comma[1] == 1'b 1 )
            begin
            next_state = STATE_TYP_SYNC_ACQ1;	
            end
         else
            begin
            next_state = STATE_TYP_COMMA_DET3;	
            end
         end
      else if (pudi_comma[0] == 1'b 0 )
         begin
         if (char_err[1] == 1'b 1)
            begin
            next_state = STATE_TYP_LOSS_SYNC;	
            end
         else if (pudi_comma[1] == 1'b 1 )
            begin
            next_state = STATE_TYP_COMMA_DET3;	
            end
         else
            begin
            next_state = STATE_TYP_COMMA_DET2;	
            end
         end
      else
         begin
         next_state = STATE_TYP_COMMA_DET2;	
         end
      end
   STATE_TYP_COMMA_DET3:
      begin
      if (signal_detect == 1'b 0)
         begin
         next_state = STATE_TYP_LOSS_SYNC;	
         end
      else if (char_err[0] == 1'b 1 )
         begin
         if (pudi_comma[1] == 1'b 1)
            begin
            next_state = STATE_TYP_COMMA_DET1;	
            end
         else
            begin
            next_state = STATE_TYP_LOSS_SYNC;	
            end
         end
      else if (pudi_comma[0] == 1'b 1 )
         begin
         if (char_err[1] == 1'b 1)
            begin
            next_state = STATE_TYP_SYNC_ACQ2;	
            end
         else
            begin
            next_state = STATE_TYP_SYNC_ACQ1;	
            end
         end
      else if (pudi_comma[0] == 1'b 0 )
         begin
         if (char_err[1] == 1'b 1)
            begin
            next_state = STATE_TYP_LOSS_SYNC;	
            end
         else if (pudi_comma[1] == 1'b 1 )
            begin
            next_state = STATE_TYP_SYNC_ACQ1;	
            end
         else
            begin
            next_state = STATE_TYP_COMMA_DET3;	
            end
         end
      else
         begin
         next_state = STATE_TYP_COMMA_DET3;	
         end
      end
   STATE_TYP_SYNC_ACQ1:
      begin
      if (signal_detect == 1'b 0)
         begin
         next_state = STATE_TYP_LOSS_SYNC;	
         end
      else if (char_err[0] == 1'b 1 )
         begin
         if (char_err[1] == 1'b 1)
            begin
            next_state = STATE_TYP_SYNC_ACQ3;	
            end
         else
            begin
            next_state = STATE_TYP_SYNC_ACQ2A;	
            end
         end
      else
         begin
         if (char_err[1] == 1'b 1)
            begin
            next_state = STATE_TYP_SYNC_ACQ2;	
            end
         else
            begin
            next_state = STATE_TYP_SYNC_ACQ1;	
            end
         end
      end
   STATE_TYP_SYNC_ACQ2:
      begin
      if (signal_detect == 1'b 0)
         begin
         next_state = STATE_TYP_LOSS_SYNC;	
         end
      else if (char_err[0] == 1'b 1 )
         begin
         if (char_err[1] == 1'b 1)
            begin
            next_state = STATE_TYP_SYNC_ACQ4;	
            end
         else
            begin
            next_state = STATE_TYP_SYNC_ACQ3A;	
            end
         end
      else
         begin
         if (char_err[1] == 1'b 1)
            begin
            next_state = STATE_TYP_SYNC_ACQ3;	
            end
         else
            begin
            next_state = STATE_TYP_SYNC_ACQ2A;	
            end
         end
      end
   STATE_TYP_SYNC_ACQ2A:
      begin
      if (signal_detect == 1'b 0)
         begin
         next_state = STATE_TYP_LOSS_SYNC;	
         end
      else if (char_err[0] == 1'b 1 )
         begin
         if (char_err[1] == 1'b 1)
            begin
            next_state = STATE_TYP_SYNC_ACQ4;	
            end
         else
            begin
            next_state = STATE_TYP_SYNC_ACQ3A;	
            end
         end
      else
         begin
         if (good_cgs == 2'b 11)
            begin
            if (char_err[1] == 1'b 1)
               begin
               next_state = STATE_TYP_SYNC_ACQ2;	
               end
            else
               begin
               next_state = STATE_TYP_SYNC_ACQ1;	
               end
            end
         else if (good_cgs == 2'b 10 )
            begin
            if (char_err[1] == 1'b 1)
               begin
               next_state = STATE_TYP_SYNC_ACQ3;	
               end
            else
               begin
               next_state = STATE_TYP_SYNC_ACQ1;	
               end
            end
         else
            begin
            if (char_err[1] == 1'b 1)
               begin
               next_state = STATE_TYP_SYNC_ACQ3;	
               end
            else
               begin
               next_state = STATE_TYP_SYNC_ACQ2A;	
               end
            end
         end
      end
   STATE_TYP_SYNC_ACQ3:
      begin
      if (signal_detect == 1'b 0)
         begin
         next_state = STATE_TYP_LOSS_SYNC;	
         end
      else if (char_err[0] == 1'b 1 )
         begin
         if (char_err[1] == 1'b 1)
            begin
            next_state = STATE_TYP_LOSS_SYNC;	
            end
         else
            begin
            next_state = STATE_TYP_SYNC_ACQ4A;	
            end
         end
      else
         begin
         if (char_err[1] == 1'b 1)
            begin
            next_state = STATE_TYP_SYNC_ACQ4;	
            end
         else
            begin
            next_state = STATE_TYP_SYNC_ACQ3A;	
            end
         end
      end
   STATE_TYP_SYNC_ACQ3A:
      begin
      if (signal_detect == 1'b 0)
         begin
         next_state = STATE_TYP_LOSS_SYNC;	
         end
      else if (char_err[0] == 1'b 1 )
         begin
         if (char_err[1] == 1'b 1)
            begin
            next_state = STATE_TYP_LOSS_SYNC;	
            end
         else
            begin
            next_state = STATE_TYP_SYNC_ACQ4A;	
            end
         end
      else
         begin
         if (good_cgs == 2'b 11)
            begin
            if (char_err[1] == 1'b 1)
               begin
               next_state = STATE_TYP_SYNC_ACQ3;	
               end
            else
               begin
               next_state = STATE_TYP_SYNC_ACQ2A;	
               end
            end
         else if (good_cgs == 2'b 10 )
            begin
            if (char_err[1] == 1'b 1)
               begin
               next_state = STATE_TYP_SYNC_ACQ4;	
               end
            else
               begin
               next_state = STATE_TYP_SYNC_ACQ2;	
               end
            end
         else
            begin
            if (char_err[1] == 1'b 1)
               begin
               next_state = STATE_TYP_SYNC_ACQ4;	
               end
            else
               begin
               next_state = STATE_TYP_SYNC_ACQ3A;	
               end
            end
         end
      end
   STATE_TYP_SYNC_ACQ4:
      begin
      if (signal_detect == 1'b 0)
         begin
         next_state = STATE_TYP_LOSS_SYNC;	
         end
      else if (char_err[0] == 1'b 1 )
         begin
         if (pudi_comma[1] == 1'b 1)
            begin
            next_state = STATE_TYP_COMMA_DET1;	
            end
         else
            begin
            next_state = STATE_TYP_LOSS_SYNC;	
            end
         end
      else
         begin
         if (char_err[1] == 1'b 1)
            begin
            next_state = STATE_TYP_LOSS_SYNC;	
            end
         else
            begin
            next_state = STATE_TYP_SYNC_ACQ4A;	
            end
         end
      end
   STATE_TYP_SYNC_ACQ4A:
      begin
      if (signal_detect == 1'b 0)
         begin
         next_state = STATE_TYP_LOSS_SYNC;	
         end
      else if (char_err[0] == 1'b 1 )
         begin
         if (pudi_comma[1] == 1'b 1)
            begin
            next_state = STATE_TYP_COMMA_DET1;	
            end
         else
            begin
            next_state = STATE_TYP_LOSS_SYNC;	
            end
         end
      else
         begin
         if (good_cgs == 2'b 11)
            begin
            if (char_err[1] == 1'b 1)
               begin
               next_state = STATE_TYP_SYNC_ACQ4;	
               end
            else
               begin
               next_state = STATE_TYP_SYNC_ACQ3A;	
               end
            end
         else if (good_cgs == 2'b 10 )
            begin
            if (char_err[1] == 1'b 1)
               begin
               next_state = STATE_TYP_LOSS_SYNC;	
               end
            else
               begin
               next_state = STATE_TYP_SYNC_ACQ3;	
               end
            end
         else
            begin
            if (char_err[1] == 1'b 1)
               begin
               next_state = STATE_TYP_LOSS_SYNC;	
               end
            else
               begin
               next_state = STATE_TYP_SYNC_ACQ4A;	
               end
            end
         end
      end
   default:
      begin
      next_state = STATE_TYP_LOSS_SYNC;   
      end
   endcase
end

//  Counter for good_cgs
// ---------------------

always @(posedge reset or posedge clk)
   begin : process_3
   if (reset == 1'b 1)
      begin
      good_cgs <= 2'b 00;	
      end
   else
      begin
      
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif       
      
              if (next_state == STATE_TYP_SYNC_ACQ2A)
                 begin
                 if (state == STATE_TYP_SYNC_ACQ2)
                    begin
                    good_cgs <= 2'b 10;	
                    end
                 else if (state != STATE_TYP_SYNC_ACQ2A )
                    begin
                    good_cgs <= 2'b 01;	
                    end
                 else
                    begin
                    good_cgs <= good_cgs + 2'b 10;	
                    end
                 end
              else if (next_state == STATE_TYP_SYNC_ACQ3A )
                 begin
                 if (state == STATE_TYP_SYNC_ACQ3)
                    begin
                    good_cgs <= 2'b 10;	
                    end
                 else if (state != STATE_TYP_SYNC_ACQ3A )
                    begin
                    good_cgs <= 2'b 01;	
                    end
                 else
                    begin
                    good_cgs <= good_cgs + 2'b 10;	
                    end
                 end
              else if (next_state == STATE_TYP_SYNC_ACQ4A )
                 begin
                 if (state == STATE_TYP_SYNC_ACQ4)
                    begin
                    good_cgs <= 2'b 10;	
                    end
                 else if (state != STATE_TYP_SYNC_ACQ4A )
                    begin
                    good_cgs <= 2'b 01;	
                    end
                 else
                    begin
                    good_cgs <= good_cgs + 2'b 10;	
                    end
                 end
              else
                 begin
                 good_cgs <= 2'b 00;	
                 end
      
         `ifdef USE_CLK_ENA
            end
         `endif      
      
      end
   end

//  Alignment Decoding
//  ------------------   			

always @(posedge reset or posedge clk)
   begin : process_4
   if (reset == 1'b 1)
      begin
      sync_acqurd <= 1'b 0;	
      enable_cgalign <= 1'b 1;	
      end
   else
      begin
      
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif       
      
              if (next_state == STATE_TYP_LOSS_SYNC | 
                 ((state == STATE_TYP_COMMA_DET1 | state == STATE_TYP_COMMA_DET2 | state == STATE_TYP_COMMA_DET3 | 
        	  state == STATE_TYP_SYNC_ACQ4 | state == STATE_TYP_SYNC_ACQ4A) & char_err[0] == 1'b 1 & next_state == STATE_TYP_COMMA_DET1))
                 begin
                 sync_acqurd <= 1'b 0;	
                 end
              else if (next_state == STATE_TYP_SYNC_ACQ1 | (next_state == STATE_TYP_SYNC_ACQ2 & state == STATE_TYP_COMMA_DET3) )
                 begin
                 sync_acqurd <= 1'b 1;	
                 end
        
              if (next_state == STATE_TYP_LOSS_SYNC)
                 begin
                 enable_cgalign <= 1'b 1;	
                 end
              else if (next_state == STATE_TYP_COMMA_DET1 | (state == STATE_TYP_LOSS_SYNC & next_state == STATE_TYP_COMMA_DET2) )
                 begin
                 enable_cgalign <= 1'b 0;	
                 end
      
         `ifdef USE_CLK_ENA
            end
         `endif      
      
      end
   end


endmodule // module rx_xgxs_sync

